package com.wingsboat.factory.support;

import com.wingsboat.exception.BeanException;
import com.wingsboat.factory.BeanFactory;
import com.wingsboat.factory.config.BeanDefinition;

/**
 * @Author: wangzhong
 * @Date: 2023/11/19 10:25
 * @Description: 抽象bean工厂
 **/

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements BeanFactory {
    @Override
    public Object getBean(String beanName) throws BeanException {
        return doGetBean(beanName, null);
    }

    @Override
    public Object getBean(String beanName, Object... args) throws BeanException {
        return doGetBean(beanName,args);
    }

    private <T> T doGetBean(String beanName,Object... args) throws BeanException {
        Object bean = getSingleton(beanName);
        if(null != bean){
            bean = getObjectForBeanInstance(bean,beanName);
            return (T)bean;
        }
        // 创建对象
        BeanDefinition beanDefinition = getBeanDefinition(beanName);
        Object object = creatBean(beanName, beanDefinition, args);
        return (T)getObjectForBeanInstance(object,beanName);
    }

    private Object getObjectForBeanInstance(Object beanInstance,String beanName) {
        if(!(beanInstance instanceof FactoryBean)){
            return beanInstance;
        }
        Object object = getCacheObjectForFactoryBean(beanName);
        if(object == null){
            FactoryBean<?> factoryBean = (FactoryBean<?>) beanInstance;
            object = getObjectFromFactoryBean(factoryBean,beanName);
        }
        return object;
    }

    @Override
    public <T> T getBean(String beanName, Class<T> requiredType) throws BeanException {
        return (T)getBean(beanName);
    }

    protected abstract <T> T creatBean(String beanName, BeanDefinition beanDefinition,Object[] args ) throws BeanException;

    protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeanException;
}
